package mips;

import i_Inst.*;
import r_Inst.*;
import j_Inst.*;
import i_Inst.Sll;

public class Decoder {


	public static void decode(String instruction) throws Exception {
		String[] splitted = instruction.split(",");
		
		if (splitted[1].equalsIgnoreCase("$zero") || splitted[1].equals("$0"))
			throw new Exception("cann't change register 0");
		
		if (splitted[0].equalsIgnoreCase("add")) 
		{
			Add.add(decodeRegister(splitted[1]),decodeRegister(splitted[2]),decodeRegister(splitted[3]));

		}
		else if (splitted[0].equalsIgnoreCase("sub"))
		{
			Sub.sub(decodeRegister(splitted[1]),decodeRegister(splitted[2]),decodeRegister(splitted[3]));

		}
		else if (splitted[0].equalsIgnoreCase("beq"))
		{
    Beq.beq(Integer.parseInt(splitted[3]), decodeRegister(splitted[1]), decodeRegister(splitted[2]));

		}
		else if (splitted[0].equalsIgnoreCase("bne"))
		{
    Bne.bne(Integer.parseInt(splitted[3]), decodeRegister(splitted[1]), decodeRegister(splitted[2]));
		}

		else if (splitted[0].equalsIgnoreCase("addi"))
		{
			Addi.addi(decodeRegister(splitted[1]),decodeRegister(splitted[2]),Integer.parseInt(splitted[3]));

		}
		else if (splitted[0].equalsIgnoreCase("and")) 
		{
			And.and(decodeRegister(splitted[1]),decodeRegister(splitted[2]),decodeRegister(splitted[3]));

		}
		else if (splitted[0].equalsIgnoreCase("or")) 
		{
			Or.or(decodeRegister(splitted[1]),decodeRegister(splitted[2]),decodeRegister(splitted[3]));

		}  
		else if (splitted[0].equalsIgnoreCase("sll"))
		{
			Sll.sll(decodeRegister(splitted[1]),decodeRegister(splitted[2]),Integer.parseInt(splitted[3]));

		}
		else if(splitted[0].equalsIgnoreCase("slti")){
			Slti.setLessThanImm(decodeRegister(splitted[1]),decodeRegister(splitted[2]),Integer.parseInt(splitted[3]));
		}
		else if(splitted[0].equalsIgnoreCase("lw")){
			int[] regAndOffset = decodeLoadOrStore(splitted[2]);
			LW.lw(decodeRegister(splitted[1]),regAndOffset[1],regAndOffset[0]);
		}
		else if(splitted[0].equalsIgnoreCase("jal")){
			Jal.jal(Integer.parseInt(splitted[1]));
		}
		else if(splitted[0].equalsIgnoreCase("jr")){
			Jr.jr(decodeRegister(splitted[1]));
		}
        	else if(splitted[0].equalsIgnoreCase("j")){
			J.j(Integer.parseInt(splitted[1]));
		}
      else if(splitted[0].equalsIgnoreCase("sw")){
			int[] regAndOffset = decodeLoadOrStore(splitted[2]);
			SW.sw(decodeRegister(splitted[1]),regAndOffset[1],regAndOffset[0]);
		}
      
      else if( splitted[0].equalsIgnoreCase("ori") ) {
Ori.ori( decodeRegister(splitted[1]),decodeRegister(splitted[2]),Integer.parseInt(splitted[3]) );
}
else if( splitted[0].equalsIgnoreCase("nor") ) {
Nor.nor( decodeRegister(splitted[1]),decodeRegister(splitted[2]),decodeRegister(splitted[3]) );
}
else if ( splitted[0].equalsIgnoreCase("slt") ) {
Slt.slt( decodeRegister(splitted[1]),decodeRegister(splitted[2]),decodeRegister(splitted[3]) );
}
else if ( splitted[0].equalsIgnoreCase("sltu") ) {
Sltu.sltu( decodeRegister(splitted[1]),decodeRegister(splitted[2]),decodeRegister(splitted[3]) );
}
else if (splitted[0].equalsIgnoreCase("andi")) {
    	  Andi.andi(decodeRegister(splitted[1]), decodeRegister(splitted[2]), 
    			  Integer.parseInt(splitted[3]));
      	}
      else if (splitted[0].equalsIgnoreCase("sltui")) {
    		  Sltui.sltui(decodeRegister(splitted[1]), decodeRegister(splitted[2]), 
    				  Integer.parseInt(splitted[3]));
      	}
      else if (splitted[0].equalsIgnoreCase("srl")) 
		{
			Srl.srl(decodeRegister(splitted[1]), decodeRegister(splitted[2]), 
					decodeRegister(splitted[3]));

		}

	}
	public static int[] decodeLoadOrStore(String splitted){
		int[] regAndOffset = new int[2];
		String [] offset = splitted.split("\\(");
		int offsetNumber = Integer.parseInt(offset[0]);
		String [] register = offset[1].split("\\)");
		int reg = decodeRegister(register[0]);
		regAndOffset[0] = offsetNumber;
		regAndOffset[1] = reg;
		return regAndOffset;
	}


	public static int decodeRegister(String register)
	{
		if(register.equals("$zero") || register.equals("$0"))
			return 0;
		else if (register.equals("$at"))
			return 1;
		else if (register.equals("$v0"))
			return 2;
		else if (register.equals("$v1"))
			return 3;
		else if (register.equals("$a0"))
			return 4;
		else if (register.equals("$a1"))
			return 5;
		else if (register.equals("$a2"))
			return 6;
		else if (register.equals("$a3"))
			return 7;
		else if (register.equals("$t0"))
			return 8;
		else if (register.equals("$t1"))
			return 9;
		else if (register.equals("$t2"))
			return 10;
		else if (register.equals("$t3"))
			return 11;
		else if (register.equals("$t4"))
			return 12;
		else if (register.equals("$t5"))
			return 13;
		else if (register.equals("$t6"))
			return 14;
		else if (register.equals("$t7"))
			return 15;
		else if (register.equals("$s0"))
			return 16;

		else if (register.equals("$s1"))
			return 17;
		else if (register.equals("$s2"))
			return 18;
		else if (register.equals("$s3"))
			return 19;
		else if (register.equals("$s4"))
			return 20;
		else if (register.equals("$s5"))
			return 21;
		else if (register.equals("$s6"))
			return 22;
		else if (register.equals("$s7"))
			return 23;
		else if (register.equals("$t8"))
			return 24;
		else if (register.equals("$t9"))
			return 25;
		else if (register.equals("$k0"))
			return 26;
		else if (register.equals("$k1"))
			return 27;
		else if (register.equals("$gp"))
			return 28;
		else if (register.equals("$sp"))
			return 29;
		else if (register.equals("$fb"))
			return 30;
		else if (register.equals("$ra"))
			return 31;	
		return -1;
	}

	public static String toBinary(int num){

		String nume = Integer.toBinaryString(num);
		return nume;
	}
	public static int toInt(String stringg){


		return (Integer.parseInt(stringg,2));

	}
	public static String AddzerostoLeft(String binary,int bits)
	{
		for(int i =0;binary.length()<bits;i++)
		{
			binary = "0"+binary;
		}
		return binary;
	}
   
   public static String signExtend(String binary,int bits)
	{
		for(int i =0;binary.length()<bits;i++)
		{
			binary = binary.charAt(0) + binary;
		}
		return binary;
	}

}
